home *** CD-ROM | disk | FTP | other *** search
- // ForestCamera.m -- render a scene of 1 (or someday more) trees
-
- #import <appkit/appkit.h>
- #import "ForestCamera.h"
- #import "Tree.h"
-
- /* 4/7/93 -- Derrived from /NextDeveloper/Examples/3Dkit/SimpleCamera
- (by Bill Bumgarner 6/1/92 with assistance from Dave Springer)
- 5/9/93 -- Derrived from Simple (By Allen King)
- */
-
- @implementation ForestCamera
-
- - awakeFromNib
- { return [self newParameter :nil]; // set values in parameter window
- }
-
- - initFrame :(const NXRect *) theRect
- { id ambientLight, pointLight;
- RtPoint xAxis = {1.0, 0.0, 0.0};
- RtPoint yAxis = {0.0, 1.0, 0.0};
- RtPoint lFromP = {0.5,0.5,0.75}; // light position point
- RtPoint fromP = {10.0,3.0,5.0}, toP = {0,0,0}; // camera position
- [super initFrame :theRect];
-
- // initialize camera
- [self setEyeAt :fromP toward :toP roll :90.0];
- redraw_mode = 1;
- dirty = 0;
-
- // create a shader that will shade surfaces with a simple matte surface.
- globalShader = [[N3DShader alloc] init];
- [(N3DShader *)globalShader setShader :"matte"];
-
- // initialize 1 tree in this ForestCamera
- theTree = [[Tree alloc] init];
- [theTree plantIn :self];
-
- // create an ambientlight source.
- ambientLight=[[N3DLight alloc] init];
- [ambientLight makeAmbientWithIntensity :0.25];
- [self addLight :ambientLight];
-
- // create a Point light and put at lFromP at full intensity (1.0).
- pointLight = [[N3DLight alloc] init];
- [pointLight makePointFrom :lFromP intensity :2.0];
- [self addLight :pointLight];
-
- // set the surface type to generate smooth solids.
- [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];
-
- // the N3DRotator object that governs rotational control via the mouseDown
- theRotator=[[N3DRotator alloc] initWithCamera :self];
-
- return self;
- }
-
- - newParameter :sender;
- { int oldBranchFactor=[theTree branchFactor], oldLevels=[theTree levels];
- int SDoldBranchFactor=[theTree SDbranchFactor];
- int SDoldLevels=[theTree SDlevels];
- int update=1;
-
- if (sender == levelsText || sender == levelsSlider)
- if ([theTree levels :[sender intValue]] == oldLevels)
- update = 0;
- if (sender == branchFactorText || sender == branchFactorSlider)
- if ([theTree branchFactor :[sender intValue]] == oldBranchFactor)
- update = 0;
- if (sender==angleText || sender==angleSlider)
- [theTree angle :[sender doubleValue]];
- if (sender == twistText || sender == twistSlider)
- [theTree twist :[sender doubleValue]];
- if (sender == shrinkText || sender == shrinkSlider)
- [theTree shrink :[sender doubleValue]];
-
- if (sender == SDbranchFactorText || sender == SDbranchFactorSlider)
- if ([theTree SDbranchFactor :[sender doubleValue]] ==SDoldBranchFactor)
- update = 0;
- if (sender == SDlevelsText || sender == SDlevelsSlider)
- if ([theTree SDlevels :[sender doubleValue]] == SDoldLevels)
- update = 0;
- if (sender == SDangleText || sender == SDangleSlider)
- [theTree SDangle :[sender doubleValue]];
- if (sender == SDtwistText || sender == SDtwistSlider)
- [theTree SDtwist :[sender doubleValue]];
- if (sender == SDshrinkText || sender == SDshrinkSlider)
- [theTree SDshrink :[sender doubleValue]];
-
- [angleSlider setFloatValue :[theTree angle]];
- [angleText setFloatValue :[theTree angle]];
- [twistSlider setFloatValue :[theTree twist]];
- [twistText setFloatValue :[theTree twist]];
- [shrinkSlider setFloatValue :[theTree shrink]];
- [shrinkText setFloatValue :[theTree shrink]];
- [SDangleSlider setFloatValue :[theTree SDangle]];
- [SDangleText setFloatValue :[theTree SDangle]];
- [SDtwistSlider setFloatValue :[theTree SDtwist]];
- [SDtwistText setFloatValue :[theTree SDtwist]];
- [SDshrinkSlider setFloatValue :[theTree SDshrink]];
- [SDshrinkText setFloatValue :[theTree SDshrink]];
- if (update)
- { [levelsSlider setIntValue :[theTree levels]];
- [levelsText setIntValue :[theTree levels]];
- [branchFactorSlider setIntValue :[theTree branchFactor]];
- [branchFactorText setIntValue :[theTree branchFactor]];
- [SDbranchFactorSlider setIntValue :[theTree SDbranchFactor]];
- [SDbranchFactorText setIntValue :[theTree SDbranchFactor]];
- [SDlevelsSlider setIntValue :[theTree SDlevels]];
- [SDlevelsText setIntValue :[theTree SDlevels]];
-
- dirty = 1;
- if (redraw_mode)
- { [theTree plantIn :self];
- [self redrawNow :nil];
- dirty = 0;
- } }
- return self;
- }
-
- #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
- - mouseDown :(NXEvent *)theEvent
- {
- int oldMask;
- NXPoint oldMouse, newMouse, dMouse;
- RtMatrix rmat, irmat;
-
- [theRotator setRotationAxis :N3D_ZAxis];
-
- // track the mouse until a mouseUp event occurs, updating the display
- // as tracking happens.
- [self lockFocus];
- oldMask = [window addToEventMask :ACTIVEBUTTONMASK];
-
- // switch to the N3D_WireFrame surface type.
- [self setSurfaceTypeForAll :N3D_WireFrame chooseHider :YES];
-
- oldMouse = theEvent->location;
- [self convertPoint :&oldMouse fromView :nil];
- while (1)
- { newMouse = theEvent->location;
- [self convertPoint :&newMouse fromView :nil];
- dMouse.x = newMouse.x - oldMouse.x;
- dMouse.y = newMouse.y - oldMouse.y;
- if (dMouse.x != 0.0 || dMouse.y != 0.0)
- { [theRotator trackMouseFrom :&oldMouse to :&newMouse
- rotationMatrix :rmat andInverse :irmat];
- [worldShape concatTransformMatrix :rmat premultiply :NO];
- [self display];
- }
- theEvent = [NXApp getNextEvent :ACTIVEBUTTONMASK];
- if (theEvent->type == NX_MOUSEUP)
- break;
- oldMouse = newMouse;
- }
- // switch back to the N3D_SmoothSolids surface type
- [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];
- [self display];
- [self unlockFocus];
-
- [window setEventMask :oldMask];
- return self;
- }
-
- - redrawNow :sender;
- { [self lockFocus];
- [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];
- [self display];
- [self unlockFocus];
- return self;
- }
-
- - redrawMode :sender;
- { int lastRedraw_mode = redraw_mode;
- redraw_mode = [sender selectedTag]? 0: 1;
- if (!(lastRedraw_mode && !redraw_mode))
- { if (dirty)
- [theTree plantIn :self];
- dirty = 0;
- [self redrawNow :nil];
- }
- return self;
- }
-
- - randomMode :sender {[theTree randomMode :sender]; return self;}
- - specis :sender {[theTree specis :sender]; return self;}
- - (int)redraw_mode {return redraw_mode;}
-
- - dumpRib :sender
- {
- static id savePanel=nil;
- NXStream *ts;
- char buf[MAXPATHLEN+1];
-
- // initialize the savePanel, if it hasn''t been done so previously
- if (!savePanel)
- { savePanel=[SavePanel new];
- [savePanel setRequiredFileType :"rib"];
- }
-
- // run the savepanel.
- if([savePanel runModal])
- { // returned w/pathname, open a stream and
- ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
- // process the file name for a custom display line such that
- // "prman <<filename>>.rib" will put the resulting image somewhere
- // predictably useful.
- strcpy(buf, [savePanel filename]);
- // remove the .rib extension from the path returned by the SavePanel
- strrchr(buf,'.')[0]='\0';
- // feed to NXPrintf to put in the custom Display command
- NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
- // then feed the rib code to the stream and
- [theTree copyRIBCode :ts];
- // save the stream to the file selected in the savepanel
- NXSaveToFile(ts, [savePanel filename]);
- // and close the stream (which also flushes it), also making sure
- // that the allocated memory is freed.
- NXCloseMemory(ts,NX_FREEBUFFER);
- }
- return self;
- }
-
- @end
-